package com.wstuo.common.exchange;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpURL;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.log4j.Logger;
import org.apache.webdav.lib.Property;
import org.apache.webdav.lib.ResponseEntity;
import org.apache.webdav.lib.WebdavResource;
import org.apache.webdav.lib.methods.DepthSupport;
import org.apache.webdav.lib.methods.PropFindMethod;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.wstuo.common.tools.dao.IEmailDAO;
import com.wstuo.common.tools.dto.EmailConnectionDTO;
import com.wstuo.common.tools.dto.EmailDTO;
import com.wstuo.common.tools.dto.EmailMessageDTO;
import com.wstuo.common.tools.dto.EmailServerDTO;
import com.wstuo.common.tools.entity.EmailMessage;
import com.wstuo.common.tools.service.IEmailServerService;
import com.wstuo.common.tools.service.IEmailService;
import com.wstuo.common.util.StringUtils;
import com.wstuo.common.util.TimeUtils;

/**
 * Exchange webdav
 * 
 * @author WSTUO
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class WebDavService implements IWebDavService {

	@Autowired
	private IEmailServerService emailServerService;
	@Autowired
	private IEmailDAO emailDAO;
	@Autowired
	private IEmailService emailService;
	private static final Logger LOGGER = Logger.getLogger(WebDavService.class);

	public static String subject= "";// 邮件标题
	public static String date= "";// 发送日期
	public static String datereceived= "";// 接收日期
	public static String displaycc= "";// 抄送
	public static String displayto= "";// 显示邮箱地址名称
	public static String from= "";// 来自邮件地址
	public static String fromemail= "";// 来自邮件地址
	public static String fromname= "";// 来自邮件名
	public static String to= "";// 接收邮件
	public static String htmldescription= "";// 邮件内容

	public static Vector properties;
	static {
		properties = new Vector();

		properties.addElement("DAV:autoversiona");
		properties.addElement("DAV:contentclass");
		properties.addElement("DAV:creationdate");
		properties.addElement("DAV:displayname");
		properties.addElement("DAV:getcontentlength");
		properties.addElement("DAV:getcontenttype");
		properties.addElement("DAV:getetag");
		properties.addElement("DAV:getlastmodified");

		properties.addElement("DAV:href");
		properties.addElement("DAV:id");
		properties.addElement("DAV:iscollection");
		properties.addElement("DAV:isfolder");
		properties.addElement("DAV:ishidden");
		properties.addElement("DAV:isreadonly");
		properties.addElement("DAV:isstructureddocument");
		properties.addElement("DAV:isversioned");
		properties.addElement("DAV:lockdiscovery");
		properties.addElement("DAV:parentname");
		properties.addElement("DAV:resourcetype");
		properties.addElement("DAV:revisionid");
		properties.addElement("DAV:revisionlabel");
		properties.addElement("DAV:revisionuri");
		properties.addElement("DAV:supportedlock");
		properties.addElement("DAV:uid");
		properties.addElement("DAV:resourcetype");
		properties.addElement("DAV:vresourceid");
		properties.addElement("urn:schemas:httpmail:date");
		properties.addElement("urn:schemas:httpmail:datereceived");
		properties.addElement("urn:schemas:httpmail:displaycc");
		properties.addElement("urn:schemas:httpmail:displayto");
		properties.addElement("urn:schemas:httpmail:from");
		properties.addElement("urn:schemas:httpmail:fromemail");
		properties.addElement("urn:schemas:httpmail:fromname");
		properties.addElement("urn:schemas:httpmail:hasattachment");

		properties.addElement("urn:schemas:httpmail:to");
		properties.addElement("urn:schemas:httpmail:htmldescription");
		properties.addElement("urn:schemas:httpmail:importance");

		properties.addElement("urn:schemas:httpmail:normalizedsubject");
		properties.addElement("urn:schemas:httpmail:read");
		properties.addElement("urn:schemas:httpmail:sendername");
		properties.addElement("urn:schemas:httpmail:subject");
		properties.addElement("urn:schemas:httpmail:submitted");
		properties.addElement("urn:schemas:httpmail:textdescription");
		properties.addElement("urn:schemas:httpmail:thread-topic");

		properties.addElement("urn:schemas:mailheader:content-class");
		properties.addElement("urn:schemas:mailheader:date");
		properties.addElement("urn:schemas:mailheader:from");
		properties.addElement("urn:schemas:mailheader:message-id");
		properties.addElement("urn:schemas:mailheader:received");
		properties.addElement("urn:schemas:mailheader:subject");
		properties.addElement("urn:schemas:mailheader:thread-index");
		properties.addElement("urn:schemas:mailheader:thread-topic");
		properties.addElement("urn:schemas:mailheader:to");
		properties.addElement("urn:schemas:mailheader:xref");
		properties.addElement("urn:schemas:mailheader:x-unsent");
		properties.addElement("urn:schemas:mailheader:x-mailer");
		properties.addElement("x-mimeole");
		properties.addElement("urn:schemas:mailheader:x-catchall");
		properties.addElement("urn:schemas:mailheader:x-ms-has-attach");
		properties.addElement("urn:schemas:mailheader:content-disposition");

	}

	/**
	 * WebdavResource连接方式
	 * 
	 * @param exchangeHostName
	 * @param exchangeEmailAccount
	 * @param exchangeUserName
	 * @param exchangePassword
	 * @param domain
	 * @return WebdavResource
	 * @throws IOException
	 */
	private WebdavResource connectWebdavResource(EmailServerDTO emailServerDTO) throws IOException {
		NTCredentials creds = new NTCredentials(
				emailServerDTO.getExchangeUserName(),
				emailServerDTO.getExchangePassword(),
				emailServerDTO.getExchangeHostName(),
				emailServerDTO.getDomain());
		
		StringBuffer inbox = new StringBuffer();
		//inbox.append( "http://" ).append( emailServerDTO.getExchangeHostName() )
		inbox.append( emailServerDTO.getExchangeHostName() )
		.append( "/exchange/" ).append( emailServerDTO.getExchangeUserName() );//.append( "/Inbox/" );
		
		HttpURL host = new HttpURL(inbox.toString());
		WebdavResource wdr = new WebdavResource(host, creds,
				WebdavResource.ALL, DepthSupport.DEPTH_INFINITY);
		return wdr;
	}

	/**
	 * 连接测试
	 * 
	 * @param emailServerDTO
	 * @return boolean
	 */
	@Transactional
	public boolean emailConnTest(EmailServerDTO emailServerDTO) {

		boolean result = true;
		try {
			if (StringUtils.hasText(emailServerDTO.getExchangeHostName())
					&& StringUtils.hasText(emailServerDTO
							.getExchangeEmailAccount())) {
				connectWebdavResource(emailServerDTO);
			} else {
				result = false;
			}
		} catch (HttpException e) {
			LOGGER.error(e);
			result = false;
		} catch (IOException ioe) {
			LOGGER.error(ioe);
			result = false;
		}
		return result;
	}

	/**
	 * 邮件信息赋值
	 */
	private void emailInfoAssignment(Enumeration responses,String inbox){
		ResponseEntity response = (ResponseEntity) responses
				.nextElement();
		Enumeration properties1 = response.getProperties();
		String properyStr = "";
		while (properties1.hasMoreElements()) {
			Property property = (Property) properties1.nextElement();
			if ("displayname".equals(property.getLocalName())) {
				properyStr = property.getPropertyAsString();
			}
			if ("date".equals(property.getLocalName())) {
				date = property.getPropertyAsString();
			}
			if ("datereceived".equals(property.getLocalName())) {
				datereceived = property.getPropertyAsString();
			}
			if ("displaycc".equals(property.getLocalName())) {
				displaycc = property.getPropertyAsString();
			}
			if ("displayto".equals(property.getLocalName())) {
				displayto = property.getPropertyAsString();
			}
			if ("from".equals(property.getLocalName())) {
				from = property.getPropertyAsString();
			}
			if ("fromemail".equals(property.getLocalName())) {
				fromemail = property.getPropertyAsString();
			}
			if ("fromname".equals(property.getLocalName())) {
				fromname = property.getPropertyAsString();
			}
			if ("to".equals(property.getLocalName())) {
				to = property.getPropertyAsString();
			}
			if ("subject".equals(property.getLocalName())) {
				subject = property.getPropertyAsString();
			}
			if ("htmldescription".equals(property.getLocalName())) {
				htmldescription = property.getPropertyAsString();
			}
			if ("hasattachment".equals(property.getLocalName())
					&& "1".equals(property.getPropertyAsString())) {
				LOGGER.info("attachment=" + inbox + properyStr);
				// fetchAttachment(inbox+mailName);
			}
		}
	}
	
	/**
	 * 获取邮箱信息
	 * 
	 * @return List<EmailMessageDTO>
	 */
	@Transactional
	public List<EmailMessageDTO> getInboxMail() {
		EmailServerDTO emailServerDTO = emailServerService.findReceiveEmail();
		List<EmailMessageDTO> list = new ArrayList<EmailMessageDTO>();
		try {
			connectWebdavResource(emailServerDTO);
			// HttpClient client=wdr.retrieveSessionInstance();
		     StringBuffer inbox = new StringBuffer();
		        //inbox.append( "http://" ).append( emailServerDTO.getExchangeHostName() )
		     inbox.append( emailServerDTO.getExchangeHostName() )
		        .append( "/exchange/" ).append( emailServerDTO.getExchangeEmailAccount() );
			PropFindMethod method = new PropFindMethod(inbox.toString(),
					Integer.MAX_VALUE, properties.elements());
			// int status = client.executeMethod(method);
			Enumeration responses = method.getResponses();
			EmailMessage lastEmail = emailDAO
					.findLastestReceiveDate(emailServerDTO
							.getExchangeEmailAccount());
			while (responses.hasMoreElements()) {
				boolean toFlag = false;
				//邮件信息赋值
				emailInfoAssignment(responses, inbox.toString());
				if (toFlag
						&& ((lastEmail == null || (StringUtils.hasText(date)
								&& lastEmail != null && lastEmail.getSendDate()
								.getTime() < str2Date(date).getTime())) && StringUtils
								.hasText(to))) {
					// 保存到数据库
					EmailMessage em = saveEmailMessage();
					// 返回List转请求
					EmailMessageDTO dto =emailMessage2EmailMessageDTO(em);
					list.add(dto);
				}
			}
		} catch (HttpException he) {
			LOGGER.error(he);
		} catch (IOException ioe) {
			LOGGER.error(ioe);
		} catch (Exception e) {
			LOGGER.error(e);
		}
		return list;
	}
	
	/**
	 * 信息转换
	 * @param em
	 * @return EmailMessageDTO
	 */
	private EmailMessageDTO emailMessage2EmailMessageDTO(EmailMessage em){
		EmailMessageDTO dto = new EmailMessageDTO();
		dto.setEmailMessageId(em.getEmailMessageId());
		dto.setSubject(subject);
		dto.setContent(htmldescription);
		dto.setFromUser(to);
		return dto;
	}
	
	/**
	 * 保存到数据库
	 */
	private EmailMessage saveEmailMessage(){
		EmailMessage em = new EmailMessage();
		em.setFolderName("INBOX");
		em.setSubject(subject);
		em.setContent(htmldescription);
		em.setFromUser(fromemail);
		em.setToUser(to);
		em.setBcc("");
		em.setCc(displaycc);
		em.setSendDate(str2Date(date));
		em.setReceiveDate(str2Date(datereceived));
		emailDAO.save(em);
		return em;
	}

	/**
	 * 字符串转日期格式
	 * 
	 * @param dateStr
	 * @return Date
	 */
	private static Date str2Date(String dateStr) {
		Date date =null;
		if (StringUtils.hasText(dateStr)) {
			dateStr = dateStr.replace("T", " ");
			date = TimeUtils.parse(dateStr,TimeUtils.DATETIME_PATTERN);
		} 
		return date;
	}


	/**
	 * exchange邮件服务器邮件发送
	 * 
	 * @param dto
	 * @return boolean
	 */
	@Transactional
	public boolean sendEmail(EmailDTO dto) {
		EmailServerDTO emailServerDTO = emailServerService.findEmail();
		EmailConnectionDTO emailConnectionDto = new EmailConnectionDTO();
		emailConnectionDto.setSmtphost(emailServerDTO.getExchangeHostName());
		emailConnectionDto.setSmtpport(25);
		emailConnectionDto.setUsername(emailServerDTO.getExchangeUserName());
		emailConnectionDto.setPassword(emailServerDTO.getExchangePassword());

		boolean result = emailService.sendMail(dto, emailConnectionDto, null);

		EmailMessage emailMessage = new EmailMessage();
		BeanUtils.copyProperties(dto, emailMessage);
		emailMessage.setFolderName("OUTBOX");
		emailMessage.setSendDate(new Date());// 发送时间
		emailMessage.setFromUser(dto.getFrom());// 发件人
		emailMessage.setToUser(receiveAddressToString(dto.getTo()));// 接收人
		emailService.saveEmailMessages(emailMessage);// 记录保存到数据
		return result;
	}

	/**
	 * 接收地址转List
	 * 
	 * @param tos
	 * @return String
	 */
	private String receiveAddressToString(List<String> tos) {
		StringBuffer sb = new StringBuffer("");
		if (tos != null) {
			for (String to : tos) {
				if (StringUtils.hasText(sb.toString())){
					sb.append(to);
				}else{
					sb.append(";" + to);
				}
			}
		}
		return sb.toString();

	}

}
